/*
 * camera.c
 *
 *  Created on: 2017年7月8日
 *      Author: Case
 */

#include "stdlib.h"
#include "r_cg_icu.h"
#include	"r_cg_riic.h"
#include "delay.h"
#include "camera.h"

#include "camera_ov7670config.h"
#include "delay.h"
#include "stdlib.h"
#include "r_cg_sci.h"


extern uint8_t ov_start;

void	Camera_Init(void)
{
	uint8_t i;
	for(i = 0;i <sizeof(ov7670_init_reg_tbl)/2;i++)
	{
		R_RIIC0_Master_Send(0x21,ov7670_init_reg_tbl[i],2);
		User_Delay(200);
	}
	Camera_FIFO_Init();
	Camera_dice(); //丢弃前两帧数据
}

void	Camera_dice()
{
	int	i = 0,x = 0,y = 0;
	if(ov_start == 2)
	{
		OV7670_OE = 0;				//使能FIFO输出
		Camera_FIFO_RRST();     //FIFO读指针复位
		for(y = 0;y < OV7670_PIX_HEIGHT;y++)
		{
			for(x = 0;x < OV7670_PIX_WIDTH;x++)
			{
				for(i = 0;i < 8;i++)
				{
					OV7670_RCLK = 0;
					OV7670_RCLK = 1;
					OV7670_RCLK = 0;
					OV7670_RCLK = 1;

					OV7670_RCLK = 0;
					OV7670_RCLK = 1;
					OV7670_RCLK = 0;
					OV7670_RCLK = 1;
				}
			}
		}
		OV7670_OE = 1;
		ov_start = 0;
	}
}

void	Camera_Read_FIFO(uint8_t threshold)
{
	uint32_t x,y,i;
	uint8_t   color;
	char	Gram[200][40];
#ifdef	OV7670_YUV422
	uint8_t 	 pix;
#endif

#ifdef	OV7670_RGB565
	uint8_t	  R,G,B,Y;
	uint16_t  pix;
#endif
	if(ov_start == 2)
	{
		OV7670_OE = 0;				//使能FIFO输出
		Camera_FIFO_RRST();     //FIFO读指针复位
		for(y = 0;y < OV7670_PIX_HEIGHT;y++)
		{
			for(x = 0;x < OV7670_PIX_WIDTH;x++)
			{
				color = 0;
				for(i = 0;i < 8;i++)
				{
#ifdef	OV7670_RGB565
					OV7670_RCLK = 0;
					pix = OV7670_DATA_BYTE&0xff;
					OV7670_RCLK = 1;
					pix <<=8;
					OV7670_RCLK = 0;
					pix |= OV7670_DATA_BYTE&0xFF;
					OV7670_RCLK = 1;
					R = ((pix >> 11)&0x1F);
					R = (R << 3)|(R&0x07);
					G = ((pix >> 5)&0x3F);
					G = (G <<2)|(G&0x03);
					B = ((pix &0x1F));
					B = (B << 3)|(B&0x07);

					Y = (R*19595+G*38469+B*7472)>>16;
					if(Y > threshold)
						color |= 0x01;
					else
						color |= 0x00;
					if(i < 7)
						color <<= 1;
#endif

#ifdef	OV7670_YUV422
					OV7670_RCLK = 0;
					pix = OV7670_DATA_BYTE;
					OV7670_RCLK = 1;
					OV7670_RCLK = 0;
					User_Delay(1);
					OV7670_RCLK = 1;
					if(pix > threshold)
						color |= 0x01;
					else
						color |= 0x00;
					if(i < 7)
							color <<= 1;
#endif
				}
				Gram[y][x] = color;
			}
		}
		OV7670_OE = 1;
		ov_start = 0;
	}
//	R_SCI1_Serial_Send_Data(Gram,8000);
//	seek_mid(Gram);
	Heading_decision(Gram);
}

uint8_t	Camear_Ostu(void)
{
	uint32_t x,y,i,j;
	uint8_t 	 pix,threshold = 0;
	float 	w0, w1, u0tmp, u1tmp, u0, u1, u, deltaTmp, deltaMax = 0;
	float 	pixelPro[256] = {0};
	int		width = OV7670_PIX_WIDTH*8;
	int		height = OV7670_PIX_HEIGHT;
    int  		pixelCount[256] = {0};
    int  		pixelSum = width * height;
    for (i = 0; i < 256; i++)
   {
	   pixelCount[i] = 0;
	   pixelPro[i] = 0;
   }
	if(ov_start == 2)
	{
		OV7670_OE = 0;				//使能FIFO输出
		Camera_FIFO_RRST();     //FIFO读指针复位
		for(y = 0;y < OV7670_PIX_HEIGHT;y++)
		{
			for(x = 0;x < OV7670_PIX_WIDTH;x++)
			{
				for(i = 0;i < 8;i++)
				{
					OV7670_RCLK = 0;
					pix = OV7670_DATA_BYTE;
					OV7670_RCLK = 1;
					OV7670_RCLK = 0;
					User_Delay(1);
					OV7670_RCLK = 1;
					pixelCount[pix]++;
				}
			}
		}
		OV7670_OE = 1;
		ov_start = 0;
	}
	 //计算每个像素在整幅图像中的比例
	    for (i = 0; i < 256; i++)
	    {
	        pixelPro[i] = (float)(pixelCount[i]) / (float)(pixelSum);
	    }

	    //经典ostu算法,得到前景和背景的分割
	    //遍历灰度级[0,255],计算出方差最大的灰度值,为最佳阈值
	    for (i = 0; i < 256; i++)//i为阈值
	    {
	        w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;

	        for (j = 0; j < 256; j++)//遍历阈值数组当i=0，1，2，3...255
	        {
	            if (j <= i) //背景部分
	            {
	                //以i为阈值分类，第一类总的概率
	                w0 += pixelPro[j];
	                u0tmp += j * pixelPro[j];
	            }
	            else       //前景部分
	            {
	                //以i为阈值分类，第二类总的概率
	                w1 += pixelPro[j];
	                u1tmp += j * pixelPro[j];
	            }
	        }

	        u0 = u0tmp / w0;        //第一类的平均灰度
	        u1 = u1tmp / w1;        //第二类的平均灰度
	        u = u0tmp + u1tmp;      //整幅图像的平均灰度
	        //计算类间方差
	        deltaTmp = w0 * (u0 - u)*(u0 - u) + w1 * (u1 - u)*(u1 - u);
	        //找出最大类间方差以及对应的阈值
	        if (deltaTmp > deltaMax)
	        {
	            deltaMax = deltaTmp;
	            threshold = i;
	        }
	    }
	    //返回最佳阈值;
	    return threshold;
}

void Camera_FIFO_Init(void)
{
	OV7670_RRST = 0;
	OV7670_WRST = 0;
	User_Delay(20);
	OV7670_RRST = 1;
	OV7670_WRST = 1;
	User_Delay(20);
	OV7670_RRST = 0;
	OV7670_WRST = 0;
}

void	Camera_FIFO_WRST(void)
{
	OV7670_WRST = 0;
	OV7670_WRST = 1;
}

void Camera_FIFO_RRST(void)
{
	OV7670_RRST = 0;
	User_Delay(1);
	OV7670_RCLK = 0;
	User_Delay(1);
	OV7670_RCLK = 1;
	User_Delay(1);
	OV7670_RCLK = 0;
	User_Delay(1);
	OV7670_RRST = 1;
	User_Delay(1);
	OV7670_RCLK = 1;
}

void Camera_FIFO_Write(uint8_t com)
{
	OV7670_WEN = com;
	Camera_FIFO_WRST();
}

void	Camera_Windows_Set(short sx,short sy,short width,short height)
{
	uint16_t endx;
	uint16_t endy;
	uint8_t   temp;
	endx=(sx+width*2)%784;	//   sx:HSTART endx:HSTOP
 	endy=sy+height*2;				//   sy:VSTRT endy:VSTOP

	//设置HREF
 	temp = Camera_IIC_RE_Reg(0x32);  	//读取Href之前的值


	temp&=0XC0;
	temp|=((endx&0X07)<<3)|(sx&0X07);
	Camera_IIC_WR_Reg(0x32,temp);
	Camera_IIC_WR_Reg(0X032,temp);
	Camera_IIC_WR_Reg(0X17,sx>>3);			//设置Href的start高8位
	Camera_IIC_WR_Reg(0X18,endx>>3);			//设置Href的end的高8位

	//设置VREF
	temp= Camera_IIC_RE_Reg(0X03);				//读取Vref之前的值
	temp&=0XF0;
	temp|=((endy&0X03)<<2)|(sy&0X03);
	Camera_IIC_WR_Reg(0X03,temp);				//设置Vref的start和end的最低2位
	Camera_IIC_WR_Reg(0X19,sy>>2);			//设置Vref的start高8位
	Camera_IIC_WR_Reg(0X1A,endy>>2);			//设置Vref的end的高8位
}

void Camera_IIC_WR_Reg(uint8_t Addr,uint8_t Dat)
{
	uint8_t Command[2];
	Command[0] = Addr;
	Command[1] = Dat;
	R_RIIC0_Master_Send(0x21,Command,2);
	User_Delay(200);
}

uint8_t Camera_IIC_RE_Reg(uint8_t Addr)
{
	uint8_t result;
	R_RIIC0_Master_Send(0x21,&Addr,1);
	User_Delay(200);
	R_RIIC0_Master_Receive(0x21,&result,1);
	User_Delay(200);
	return result;
}



